(loading path.ps...)print

% path == <<
%             0 << subpath0 >>
%             1 << %subpath1
%                   0  << elem0 /move >> %first elem must be /move
%                   1  << elem1 >>
%               >>
%         >>
% A /move element will always start a new subpath
% Any other element appends to the last subpath

% Path Construction Operators

% -  newpath  -
% initialize current path to be empty
/newpath {
    graphicsdict /currgstate get
        /currpath 1 dict put
} bind def

% -  currentpoint  x y
% return current point coordinates
/currentpoint {
    cpath dup length 0 eq {
        pop /currentpoint cvx /nocurrentpoint signalerror
    }{
        dup length 1 sub get % last-subpath
        dup length 1 sub get % last-elem
        /data get dup length 2 sub 2 getinterval % last data pair
        aload pop itransform
    } ifelse
} bind def

/cpath { graphicsdict /currgstate get /currpath get } bind def

/addtopath { % << /data [...] /cmd /... >> <<path>>
    %(addtopath)=
    %(addtopath start pstack:)= pstack()=
    dup length 0 eq {                       % elem path
        1 index /cmd get /move eq {         % elem path
            %(New Path)=
            << 0 4 3 roll >> % new subpath  % <path> <subpath>
            0 exch put                      %
        }{
            /addtopath cvx /nocurrentpoint signalerror
        } ifelse
    }{                                  % elem path
        1 index /cmd get /move eq {     % elem path
            dup dup length 1 sub get    % elem path last-subpath
            dup length 1 sub get        % elem path last-elem-of-last-subpath
            dup /cmd get /move eq { % elem path last-elem
                %(Merge /move)=
                3 1 roll pop            % last-elem elem
                /data get /data exch put
            }{                          % elem path last-elem
                %(New subpath)=
                pop                     % elem path
                dup length 3 2 roll     % <path> n <elem>
                << 0 3 2 roll >>        % <path> n <<0 <elem>>>        % new subpath
                %pstack()=
                put
            } ifelse
        }{                              % elem path
            %(Append elem)=
            dup length 1 sub get        % elem last-subpath
            dup length                  % elem last-subpath key
            3 2 roll
            %pstack()=
            put     
        } ifelse
    } ifelse
    %(addtopath final pstack:)= pstack()=
    %(addtopath exit)=
} bind def

% x y  moveto  -
% set current point to (x,y)
/moveto {
    transform
    2 array astore
    << /data 3 2 roll /cmd /move >> cpath addtopath
} bind def

% dx dy  rmoveto  -
% relative moveto
/rmoveto {
    currentpoint
    3 2 roll add
    3 1 roll add exch
    moveto
} bind def

% x y  lineto  -
% append straight line to (x,y)
/lineto {
    transform
    2 array astore
    << /data 3 2 roll /cmd /line >> cpath addtopath
} bind def

% dx dy  rlineto  -
% relative lineto
/rlineto {
    currentpoint
    3 2 roll add
    3 1 roll add exch
    lineto
} bind def

% x1 y1 x2 y2 x3 y3  curveto  -
% append Bezier cubic section
/curveto {
    3 { 6 2 roll transform } repeat
    6 array astore
    << /data 3 2 roll /cmd /curve >> cpath addtopath
} bind def

% dx1 dy1 dx2 dy2 dx3 dy3  rcurveto  -
% relative curveto
/rcurveto {
    3 {
        6 2 roll currentpoint
        3 2 roll add
        3 1 roll add exch
    } repeat
    curveto
} bind def

/tan {
    dup sin exch
    cos exch div
} def

% packs the center-point, radius and center-angle in a matrix
% then performs the simpler task of calculating a bezier
% for the arc that is symmetrical about the x-axis
% formula derived from http://www.tinaja.com/glib/bezarc1.pdf
/arcbez { % draw single bezier % x y r angle1 angle2
	DICT
    %5 dict
	begin
    %/mat matrix def
    5 3 roll mat translate pop                         % r angle1 angle2
    3 2 roll dup mat1 scale mat mat concatmatrix pop % angle1 angle2
    2 copy exch sub /da exch def                       % da=a2-a1
    add 2 div mat1 rotate mat mat concatmatrix pop
    /da_2 da 2 div def
    /sin_a da_2 sin def
    /cos_a da_2 cos def
    4 cos_a sub 3 div % x1
    1 cos_a sub cos_a 3 sub mul
    3 sin_a mul div   % x1 y1
    neg
    1 index           % x1 y1 x2(==x1)
    1 index neg       % x1 y1 x2 y2(==-y1)
    cos_a sin_a neg   % x1 y1 x2 y2 x3 y3
    cos_a sin_a       %               ... x0 y0
    4 { 8 2 roll mat transform } repeat
    %pstack()=
    end
}
dup 0 10 dict
	dup /mat matrix put
	dup /mat1 matrix put
put
bind
def

% x y r angle1 angle2  arc  -
% append a counterclockwise circular arc to the current path
/arc {
    dup 0 lt { 360 add exch 360 add exch } if
    1 index 0 lt { 360 add exch 360 add exch } if
    2 { dup 720 gt { dup 720 div truncate 720 mul sub } if exch } repeat
    2 copy gt { 360 add } if % s.b. angle2 > angle1
    %2 { dup 0 lt { 360 add } if exch } repeat
    2 copy gt { 360 add } if % s.b. angle2 > angle1
    2 copy exch sub dup 90 gt { % recurse
        .5 mul % x y r a1 a2 da/2
        6 copy
        sub arc
        3 2 roll add exch arc
    }{ pop
        % draw single bezier
        arcbez % x1 y1 x2 y2 x3 y3 x0 y0
        4 2 roll % x1 y1 x2 y2 x0 y0  x3 y3
        %{ currentpoint pop pop } stopped { moveto }{ lineto } ifelse
		cpath length 0 eq { moveto }{ lineto } ifelse
        6 2 roll % x0 y0 x1 y1 x2 y2
        4 2 roll % x0 y0 x2 y2 x1 y1
        6 4 roll % x2 y2 x1 y1 x0 y0
        curveto
    } ifelse
}
bind
def

/arcn {
    dup 0 lt { 360 add exch 360 add exch } if
    1 index 0 lt { 360 add exch 360 add exch } if
    2 { dup 720 gt { dup 720 div truncate 720 mul sub } if exch } repeat
    2 copy lt { exch 360 add exch } if % s.b. angle1 > angle2
    %2 { dup 0 lt { 360 add } if exch } repeat
    2 copy lt { exch 360 add exch } if % s.b. angle1 > angle2
    2 copy sub dup 90 gt { % recurse
        .5 mul % x y r a1 a2 da/2
        6 copy
        3 2 roll exch sub exch arcn
        add arcn
    }{ pop
        % draw single bezier
        arcbez % x1 y1 x2 y2 x3 y3  x0 y0
        %4 2 roll
        %{ currentpoint pop pop } stopped { moveto }{ lineto } ifelse
		cpath length 0 eq { moveto }{ lineto } ifelse
        %6 2 roll
        %4 2 roll
        %6 4 roll
        curveto
    } ifelse
}
bind
def

% -  closepath  -
% connect subpath back to its starting point
/closepath {
    cpath length 0 gt {
        cpath dup length 1 sub get % subpath
        dup dup length 1 sub get % subpath last-elem
        /cmd get /close eq { % subpath
            pop
        }{                   % subpath
            0 get /data get % subpath [data]
            << /data 3 2 roll /cmd /close >> cpath addtopath
        } ifelse
    } if
} bind def

/median { % P0 P3 = x0 y0 x1 y1
    3 -1 roll add .5 mul % x0 x1 y0+y1/2
    3 1 roll add .5 mul  % (y0+y1)/2 (x0+x1)/2
    exch % (1/2)(P0+P3)
} bind def

/dist { % P1 P2 = x1 y1 x2 y2
    3 -1 roll sub dup mul % x1 x2 (y2-y1)^2
    3 1 roll exch sub dup mul % (y2-y1)^2 (x2-x1)^2
    add sqrt % dist
} bind def

%FIXME: account for device resolution
%calculate the pythagorean distance between the
% midpoint of the bezier curve and the midpoint of the straight line
/checkflat { % P0 P1 P2 P3
    8 copy
    exch .125 mul exch .125 mul 8 2 roll % (1/8)P3 P0 P1 P2
    exch .375 mul exch .375 mul 8 2 roll % (3/8)P2 (1/8)P3 P0 P1
    exch .375 mul exch .375 mul 8 2 roll % (3/8)P1 (3/8)P2 (1/8)P3 P0
    exch .125 mul exch .125 mul 8 2 roll % (1/8)P0 (3/8)P1 (3/8)P2 (1/8)P3
    3 -1 roll add 3 1 roll add exch      %                        +
    3 -1 roll add 3 1 roll add exch      %                +
    3 -1 roll add 3 1 roll add exch      %        +
    10 2 roll                            % B(1/2) P0 P1 P2 P3
    8 2 roll pop pop pop pop             % B(1/2) P0 P3
    median % B(1/2) (1/2)(P0+P3)
    dist
} bind def

/getpair { % xN yN .. x0 y0 N  getpair  xN yN .. x0 y0 xN yN
               % a0 a1 b0 b1 1
    2 mul      % a0 a1 b0 b1 2
    2 add dup  % a0 a1 b0 b1 4 4
    index      % a0 a1 b0 b1 4 a0
    exch 1 sub % a0 a1 b0 b1 a0 3
    index      % a0 a1 b0 b1 a0 a1
} bind def

% P'0 = P0           = P0
% P'1 = P01          = P0 P1 median
%       P12          = P1 P2 median
% P'2 = P012         = P01 P12  median
% P'3 = P0123 = P''0 = P012 P123 median
%        P123 = P''1 = P12 P23 median
%         P23 = P''2 = P2 P3 median
%          P3 = P''3 = P3
/chopcurve { % <</cmd /curve /data [...]>>
    flattendict /cp get aload pop
    2 index /data get aload pop
    checkflat % curve-error
    %(checkflat)= dup =
    currentflat gt {
        /data get aload pop
        flattendict /cp get aload pop 8 2 roll % P0 P1 P2 P3
        %(median)=
        %pstack()=
        3 getpair 3 getpair median % P0 P1 P2 P3 P01
        %(median)=
        3 getpair 3 getpair median % P0 P1 P2 P3 P01 P12
        3 getpair 3 getpair median % P0 P1 P2 P3 P01 P12 P23
        2 getpair 2 getpair median % P0 P1 P2 P3 P01 P12 P23 P012
        2 getpair 2 getpair median % P0 P1 P2 P3 P01 P12 P23 P012 P123
        1 getpair 1 getpair median % P0 P1 P2 P3 P01 P12 P23 P012 P123 P0123
        %(median)=
                           %drop   % X  X  X  "  '   X   "   '    "    '
                          %curve1  %          |  P'1     |   P'2  |    P'3
                          %curve2  %          P"3        P"2      P"1
                      %pair index  % 9  8  7  6  5   4   3   2    1    0
                          %count   % 20 18 16 14 12  10  8   6    4    2
        20 -2 roll pop pop         %    P1 P2 P3 P01 P12 P23 P012 P123 P0123
        18 -2 roll pop pop         %       P2 P3 P01 P12 P23 P012 P123 P0123
        16 -2 roll pop pop         %          P3 P01 P12 P23 P012 P123 P0123
        10 -2 roll pop pop         %          P3 P01     P23 P012 P123 P0123
                                   %          P"3 P'1    P"2 P'2 P"1 P'3
        4 -2 roll                  %          P"3 P'1    P"2 P'2    P'3 P"1
        8 -2 roll                  %          P"3 P'1       P'2    P'3 P"1 P"2
        12 -2 roll                 %             P'1      P'2 P'3    P"1 P"2 P"3
        6 array astore
        << /data 3 2 roll /cmd /curve >> %   P'1 P'2 P'3   <P"1 P"2 P"3>
        7 1 roll                   %        <P"1 P"2 P"3>  P'1 P'2 P'3 
        6 array astore
        << /data 3 2 roll /cmd /curve >> %  <P"1 P"2 P"3>  <P'1 P'2 P'3>
        dup /data get 4 2 getinterval exch %  <P"1 P"2 P"3> [P'3] <P'1 P'2 P'3>
        chopcurve
        flattendict exch /cp exch put
        chopcurve
    }{
        dup /data get 4 2 getinterval flattendict exch /cp exch put
        << /data 3 2 roll /data get 4 2 getinterval /cmd /line >>
        cpath addtopath
    } ifelse
} bind def

/flattendict <<
    /move {
        dup /data get flattendict exch /cp exch put
        cpath addtopath }
    /line {
        dup /data get flattendict exch /cp exch put
        cpath addtopath }
    /curve {
        chopcurve
        %dup /data get 4 2 getinterval flattendict exch /cp exch put
        %<< /data 3 2 roll /data get 4 2 getinterval /cmd /line >>
        %cpath addtopath
    }
    /close {
        dup /data get flattendict exch /cp exch put
        cpath addtopath }
>> def

/flattenpath {
    cpath length 0 gt {
        cpath newpath
        0 1 2 index length 1 sub { % path i
            2 copy get             % path i subpath_i
            0 1 2 index length 1 sub { % p i sp_i j
                2 copy get             % p i sp_i j sp_i_j
                flattendict 1 index /cmd get get exec
                pop                    % p i sp_i
            } for
            pop pop
        } for
        pop
    } if
} bind def

/reversedict <<
    /close { % p i sp_i j sp_i_j
        dopending
        reversedict /pending /line put
        reversedict /isclosed true put
    }
    /line {
        dopending
        reversedict /pending /line put
    }
    /curve {
        dup /data get exch
        dopending
        reversedict /pending /curve put
        reversedict /curvedata 3 2 roll put
    }
    /move {
        reversedict /isclosed get {
            pop closepath
        }{
            dopending
        } ifelse
    }
>> def

/pendingdict <<
    /move {
        dup /cmd /move put
        dup /data 2 copy get dup length 2 sub 2 getinterval put %final point if curve
    }
    /line {
        dup /cmd /line put
        dup /data 2 copy get dup length 2 sub 2 getinterval put %final point if curve
    }
    /curve {
        dup /cmd /curve put
        dup /data 2 copy get
        dup length 2 sub 2 getinterval aload pop % el el /data x y
        reversedict /curvedata get               % el el /data x y arr
        aload pop pop pop 4 2 roll 6 4 roll
        6 array astore                           % el el /data arr
        put                                      % el
    }
    /close { }
>> def
/dopending {
    pendingdict reversedict /pending get get exec
    cpath addtopath
} bind def

/reversepath {
    cpath length 0 gt {
        cpath newpath
        0 1 2 index length 1 sub { % path i
            2 copy get             % path i subpath_i
            reversedict /pending /move put
            reversedict /isclosed false put
            dup length 1 sub -1 0 { % p i sp_i j
                2 copy get          % p i sp_i j sp_i_j
                reversedict 1 index /cmd get get exec
                pop                 % p i sp_i
            } for
            pop pop
        } for
        pop
    } if
} bind def

% produce a vector from two points
/ptdiff { % P0 P1
    3 -1 roll sub
    3 1 roll exch sub exch % dx dy
} bind def

% convert cartesian vector to polar
/magang { % dx dy  .  rad ang
    2 copy 
    dup mul exch dup mul add sqrt
    3 1 roll exch atan
} bind def

% convert polar vector to cartesian
/ravec { % rad ang  .  dx dy
    dup cos 2 index mul  % rad ang rad*cos(ang)
    3 1 roll sin mul     % rad*cos(ang) rad*sin(ang)
} bind def

/minlinewidth {
    currentlinewidth
    dup 1 lt { pop 1 } if
} bind def

/dolinejoin { % RR|LL R|L C
    {
        { moveto lineto lineto closepath } % miter join
        { % XX X C
            6 4 roll pop pop
            2 copy moveto % X C
            2 copy 6 2 roll % C X C
            ptdiff dup mul exch dup mul add sqrt % C r
            0 360 arc
            closepath
        } % round join
        { moveto lineto lineto closepath } % bevel join
    } currentlinejoin get exec
} def

%
% replace lineto segments . with 
%                         |              L LL
%                         |              /C--
%       1 rmoveto --.-- closepath 5     /
%       2 rlineto |   |                      /
%                 |   | rlineto 4       ---C/
%                 |----                   R RR
%         3 rlineto ^---moveto 6
%                 R C L
%           point 2   point 3
%                 ----
%                 |  | join
%                 ----
%                 1  4
%           point RR  point LL
/strokedict <<
    /ang 0
    /oldcp 2 array
    /cp 2 array
    /oldpointR 2 array
    /oldpointL 2 array
    /pointR 2 array
    /pointRR 2 array
    /pointL 2 array
    /pointLL 2 array
    /move {
        %strokedict /cp 2 index /data get put
        dup /data get strokedict /cp get copy pop
        cpath addtopath
        strokedict /justmoved true put
    }
    /line { % el

        strokedict /cp get aload pop       % el x0 y0
        2 index /data get aload pop        % el x0 y0 x1 y1
        strokedict /cp get strokedict /oldcp get copy pop % oldcp
        2 copy strokedict /cp get astore pop % cp=(x1 y1)

        ptdiff                             % el dx dy
        magang                             % el rad ang
        strokedict /oldang strokedict /ang get put
        strokedict /ang 2 index put                        % ang=atan(dy/dx)
        strokedict /justmoved get {
            strokedict /firstang 2 index put
        } if
        /DEBUGSTROKE where { pop (A)= pstack()= } if

        minlinewidth
        .5 mul 1 index 90 sub % el rad ang .5lw ang_perp
        ravec %idtransform
        rmoveto              % el rad ang      %rmoveto 1
        currentpoint strokedict /pointRR get astore pop % ptRR

        2 copy ravec %idtransform
        rlineto              % el rad ang      %rlineto 2
        strokedict /pointR get strokedict /oldpointR get copy pop % oldptR
        currentpoint strokedict /pointR get astore pop % ptR

        minlinewidth
        1 index 90 add       % el rad ang lw -ang_perp
        ravec %idtransform
        rlineto              % el rad ang      %rlineto 3
        strokedict /pointL get strokedict /oldpointL get copy pop % oldptL
        currentpoint strokedict /pointL get astore pop % ptL

        180 add ravec %idtransform
        rlineto              % el rad ang      %rlineto 4
        currentpoint strokedict /pointLL get astore pop % ptLL

        closepath            % el              %closepath 5
        pop  % discard original lineto element
        /DEBUGSTROKE where { pop (B)= pstack()= } if

        strokedict /justmoved get {
            strokedict /firstRR strokedict /pointRR get 2 array copy put
            strokedict /firstLL strokedict /pointLL get 2 array copy put
        } if

        strokedict /justmoved get not { % draw join
            strokedict /ang get strokedict /oldang get sub
            /DEBUGSTROKE where { pop (C)= pstack()= } if
            dup 0 le exch 180 ge or { % right turn

                strokedict /pointLL get aload pop
                strokedict /oldpointL get aload pop
                strokedict /oldcp get aload pop
                dolinejoin

                /DEBUGSTROKE where { pop (D)= pstack()= } if
                closepath
            }{ % left turn

                strokedict /pointRR get aload pop
                strokedict /oldpointR get aload pop 
                strokedict /oldcp get aload pop 
                dolinejoin

                /DEBUGSTROKE where { pop (E)= pstack()= } if
                closepath
            } ifelse
        } if

        strokedict /cp get 2 array copy
        << /data 3 2 roll /cmd /move >> cpath addtopath % moveto 6

        strokedict /justmoved false put
    }
    /close { % el

        strokedict /cp get aload pop       % el x0 y0
        2 index /data get aload pop        % el x0 y0 x1 y1
        strokedict /cp get strokedict /oldcp get copy pop % oldcp
        2 copy strokedict /cp get astore pop % cp=(x1 y1)

        ptdiff                             % el dx dy
        magang                             % el rad ang
        strokedict /oldang strokedict /ang get put
        strokedict /ang 2 index put                        % ang=atan(dy/dx)
        /DEBUGSTROKE where { pop (A)= pstack()= } if

        minlinewidth
        .5 mul 1 index 90 sub % el rad ang .5lw ang_perp
        ravec %idtransform
        rmoveto              % el rad ang      %rmoveto 1
        currentpoint strokedict /pointRR get astore pop % ptRR

        2 copy ravec %idtransform
        rlineto              % el rad ang      %rlineto 2
        strokedict /pointR get strokedict /oldpointR get copy pop % oldptR
        currentpoint strokedict /pointR get astore pop % ptR

        minlinewidth
        1 index 90 add       % el rad ang lw -ang_perp
        ravec %idtransform
        rlineto              % el rad ang      %rlineto 3
        strokedict /pointL get strokedict /oldpointL get copy pop % oldptL
        currentpoint strokedict /pointL get astore pop % ptL

        180 add ravec %idtransform
        rlineto              % el rad ang      %rlineto 4
        currentpoint strokedict /pointLL get astore pop % ptLL

        closepath            % el              %closepath 5
        pop  % discard original lineto element
        /DEBUGSTROKE where { pop (B)= pstack()= } if

        strokedict /justmoved get not { % draw join
            strokedict /ang get strokedict /oldang get sub
            /DEBUGSTROKE where { pop (C)= pstack()= } if
            dup 0 le exch 180 ge or { % right turn

                strokedict /pointLL get aload pop
                strokedict /oldpointL get aload pop
                strokedict /oldcp get aload pop
                dolinejoin

                /DEBUGSTROKE where { pop (D)= pstack()= } if
                closepath
            }{ % left turn

                strokedict /pointRR get aload pop
                strokedict /oldpointR get aload pop
                strokedict /oldcp get aload pop
                dolinejoin

                /DEBUGSTROKE where { pop (E)= pstack()= } if
                closepath
            } ifelse

            %draw final line join
            strokedict /firstang get strokedict /ang get sub
            dup 0 le exch 180 ge or { % right turn

                strokedict /firstLL get aload pop
                strokedict /pointL get aload pop
                strokedict /cp get aload pop
                dolinejoin

                closepath
            }{ % left turn

                strokedict /firstRR get aload pop
                strokedict /pointR get aload pop
                strokedict /cp get aload pop
                dolinejoin

                closepath
            } ifelse

        } if

        strokedict /cp get 2 array copy
        << /data 3 2 roll /cmd /move >> cpath addtopath % moveto 6

        strokedict /justmoved false put
    }
    %pstack()=
    /curve { pop } %s.b. eliminated by flattenpath
>> def

/strokepath {
    flattenpath
    matrix currentmatrix
    matrix setmatrix
    cpath length 0 gt {
        cpath newpath
        0 1 2 index length 1 sub { % path i
            2 copy get             % path i subpath_i
            dup length 0 gt {
                0 1 2 index length 1 sub { % p i sp_i j
                    2 copy get             % p i sp_i j sp_i_j
                    strokedict 1 index /cmd get get exec
                    %(sd:)= pstack()=
                    pop                    % p i sp_i
                } for              % p i sp_i
            } if
            pop pop                % path
        } for
        pop
    } if
    %(sp:)= pstack()=
    %dup type /arraytype ne {pop} if
    %dup type /arraytype ne {pop} if
    setmatrix
} bind def

/maxmin {
    2 copy
    dup maxy gt { /maxy exch def }{ pop } ifelse
    dup maxx gt { /maxx exch def }{ pop } ifelse
    dup miny lt { /miny exch def }{ pop } ifelse
    dup minx lt { /minx exch def }{ pop } ifelse
} bind def

/clippath {
    graphicsdict /currgstate get
        dup /clipregion get
        /currpath exch put
} bind def

/pathbbox {
    cpath length 0 eq {
        0 0 0 0
    }{
        << /minx 16#7fffffff /miny 1 index
            /maxx 1 index neg /maxy 1 index >> begin
        cpath
        0 1 2 index length 1 sub {
            2 copy get
            0 1 2 index length 1 sub {
                2 copy get
                /data get
                aload length 2 idiv
                { maxmin } repeat
                pop
            } for
            pop pop
        } for
        pop
        minx miny maxx maxy
        end
    } ifelse
} bind def

% move line curve close  pathforall  -
% enumerate current path
/pathforall {
DICT
%5 dict
begin
    {close curve line move}{exch def}forall
    0 1 cpath length 1 sub {
        /cp exch def
        0 1 cpath cp get % subpath
        length 1 sub {
            cpath cp get exch get % elem
            dup /cmd get /close ne {
                dup /data get % elem [data]
                aload length  % elem d a t a n
                dup 2 eq {
                    pop
                    itransform
                    3 2 roll
                }{
                    6 eq {
                        6 2 roll itransform
                        6 2 roll itransform
                        6 2 roll itransform
                        7 6 roll
                    }{
                        /pathforall cvx /unregistered signalerror
                    } ifelse
                } ifelse
                %1 add -1 roll % d a t a elem
            } if
            /cmd get cvx exec
        } for
    } for
end
}
dup 0 10 dict put
bind def

% move line curve close  .devpathforall  -
% enumerate current path
/.devpathforall {
DICT
%5 dict
begin
    {close curve line move}{exch def}forall
    0 1 cpath length 1 sub {
        /cp exch def
        0 1 cpath cp get % subpath
        length 1 sub {
            cpath cp get exch get % elem
            dup /cmd get /close ne {
                dup /data get % elem [data]
                aload length  % elem d a t a n
                1 add -1 roll % d a t a elem
            } if
            /cmd get cvx exec
        } for
    } for
end
}
dup 0 10 dict put
bind def

(eof path.ps\n)print
